package com.itheima.reggie.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.itheima.reggie.dto.DishDto;
import com.itheima.reggie.entity.Category;
import com.itheima.reggie.entity.Dish;
import com.itheima.reggie.entity.DishFlavor;
import com.itheima.reggie.entity.Page;
import com.itheima.reggie.mapper.CategoryMapper;
import com.itheima.reggie.mapper.DishFlavorMapper;
import com.itheima.reggie.mapper.DishMapper;
import com.itheima.reggie.service.DishService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class DishServiceImpl implements DishService {
    @Autowired(required = false)
    private DishMapper dishMapper;
    @Autowired(required = false)
    private DishFlavorMapper dishFlavorMapper;
    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public Page<DishDto> findByPage(Integer page, Integer pageSize, String name) {
        PageHelper.startPage(page, pageSize);
        List<DishDto> dishDtoList = dishMapper.findByPage(name);
        PageInfo<DishDto> dishDtoPageInfo = new PageInfo<>(dishDtoList);
        Page<DishDto> dishDtoPage = new Page<>();
        dishDtoPage.setTotal(dishDtoPageInfo.getTotal());
        dishDtoPage.setRecords(dishDtoPageInfo.getList());
        return dishDtoPage;
    }

    @Override
    @Transactional
    public void save(DishDto dishDto) {
        dishDto.setCreateTime(LocalDateTime.now());
        dishDto.setUpdateTime(LocalDateTime.now());
        dishDto.setStatus(1);
        dishDto.setSort(0);
        dishMapper.save(dishDto);
        List<DishFlavor> dishFlavors = dishDto.getFlavors();
        //判断口味数据存在
        if (dishFlavors.size() != 0) {
            dishFlavors.forEach(item -> {
                item.setDishId(dishDto.getId());
                item.setCreateUser(dishDto.getCreateUser());
                item.setUpdateUser(dishDto.getUpdateUser());
                item.setCreateTime(LocalDateTime.now());
                item.setUpdateTime(LocalDateTime.now());
            });
            dishFlavorMapper.save(dishFlavors);
           //由于菜品的数据已经发生变化了，那么需要清空缓存
            Set keys = redisTemplate.keys("dish_*");
            redisTemplate.delete(keys);
        }
    }

    @Override
    @Transactional
    public void delete(List<Long> ids) {
        dishMapper.delete(ids);
        dishFlavorMapper.delete(ids);
        //由于菜品的数据已经发生变化了，那么需要清空缓存
        Set keys = redisTemplate.keys("dish_*");
        redisTemplate.delete(keys);
    }

    @Override
    public DishDto findById(long id) {
        DishDto dishDto = dishMapper.findById(id);
        return dishDto;
    }

    @Override
    public void update(DishDto dishDto) {
        dishDto.setUpdateTime(LocalDateTime.now());
        dishMapper.update(dishDto);
        dishFlavorMapper.deleteById(dishDto.getId());
        List<DishFlavor> flavors = dishDto.getFlavors();
        flavors.forEach(item -> {
            item.setUpdateTime(LocalDateTime.now());
            item.setUpdateUser(dishDto.getUpdateUser());
            if (item.getDishId() == null) {
                item.setDishId(dishDto.getId());
                item.setUpdateUser(dishDto.getUpdateUser());
                item.setUpdateTime(LocalDateTime.now());
                item.setCreateTime(LocalDateTime.now());
                item.setCreateUser(dishDto.getCreateUser());
            }
        });
        dishFlavorMapper.save(flavors);
        //由于菜品的数据已经发生变化了，那么需要清空缓存
        Set keys = redisTemplate.keys("dish_*");
        redisTemplate.delete(keys);
    }

    @Autowired(required = false)
    private CategoryMapper categoryMapper;

    /**
     * 根据类别Id查询菜品列表的方法
     *
     * @param cid    查询类别id
     * @param status 查询状态
     * @return List 返回的菜品列表
     */
    @Override
    public List<DishDto> findAllByCid(Long cid, Integer status) {
        List<DishDto> dishDtoList = null;
        ValueOperations valueOperations = redisTemplate.opsForValue();
        String key = "dish_" + cid + "_" + status;
        dishDtoList = (List<DishDto>) valueOperations.get(key);
        if (dishDtoList == null) {
        //1.查询了菜品列表（每个菜品没有包含口味列表）
        List<Dish> dishList = dishMapper.findAllByCid(cid,status);
        //项查询菜品的时候同时查询口味列表有2种做法：
        //第一种：sql语句进行多表查询映射，菜品表与口味表多表查询
        //第二种：先查询菜品列表，遍历，根据每个菜品id查询口味列表，最后将菜品与口味都封装DishDto中（本次使用）
        //2.定义DishDto列表集合接收所有菜品及其菜品的口味
        //3.遍历dishList菜品列表
        dishDtoList = dishList.stream().map(dish -> {
            //根据菜品id查询口味列表
            List<DishFlavor> dishFlavorList = dishFlavorMapper.findAllByDishId(dish.getId());
            //封装到DishDto
            DishDto dishDto = new DishDto();
            dishDto.setFlavors(dishFlavorList);
            //将dish对象中所有属性数据赋值给dishDto的属性数据
            BeanUtils.copyProperties(dish, dishDto);
            //根据类别id查询类别对象
            Category category = categoryMapper.findByCid(cid);
            //封装类别名称到DishDto
            dishDto.setCategoryName(category.getName());
            return dishDto;
        }).collect(Collectors.toList());
            valueOperations.set(key,dishDtoList,60*24,TimeUnit.MINUTES);
    }
        return dishDtoList;
    }

    @Override
    public void updateStatus(List<Long> ids, Integer status) {
        dishMapper.updateStatus(ids, status);
    }
}
